[][src]Crate hawk

The hawk crate provides support for Hawk authentictation. It is a low-level crate, used by higher-level crates to integrate with various Rust HTTP libraries. For example hyper-hawk integrates Hawk with Hyper.

Examples

Hawk Client

A client can attach a Hawk Authorization header to requests by providing credentials to a Request instance, which will generate the header.

use hawk::{RequestBuilder, Credentials, Key, SHA256, PayloadHasher};
use std::time::{Duration, UNIX_EPOCH};

fn main() {
    // provide the Hawk id and key
    let credentials = Credentials {
        id: "test-client".to_string(),
        key: Key::new(vec![99u8; 32], SHA256).unwrap(),
    };

    let payload_hash = PayloadHasher::hash("text/plain", SHA256, "request-body").unwrap();

    // provide the details of the request to be authorized
     let request = RequestBuilder::new("POST", "example.com", 80, "/v1/users")
        .hash(&payload_hash[..])
        .request();

    // Get the resulting header, including the calculated MAC; this involves a random
    // nonce, so the MAC will be different on every request.
    let header = request.make_header(&credentials).unwrap();

    // the header would the be attached to the request
    assert_eq!(header.id.unwrap(), "test-client");
    assert_eq!(header.mac.unwrap().len(), 32);
    assert_eq!(header.hash.unwrap().len(), 32);
}

A client that wishes to use a bewit (URL parameter) can do so as follows:

use hawk::{RequestBuilder, Credentials, Key, SHA256, Bewit};
use std::time::Duration;
use std::borrow::Cow;

let credentials = Credentials {
    id: "me".to_string(),
    key: Key::new("tok", SHA256).unwrap(),
};

let client_req = RequestBuilder::new("GET", "mysite.com", 443, "/resource").request();
let client_bewit = client_req
    .make_bewit_with_ttl(&credentials, Duration::from_secs(10))
    .unwrap();
let request_path = format!("/resource?bewit={}", client_bewit.to_str());
// .. make the request

Hawk Server

To act as a server, parse the Hawk Authorization header from the request, generate a new Request instance, and use the request to validate the header.

use hawk::{RequestBuilder, Header, Key, SHA256};
use hawk::mac::Mac;
use std::time::{Duration, UNIX_EPOCH};

fn main() {
   let mac = Mac::from(vec![7, 22, 226, 240, 84, 78, 49, 75, 115, 144, 70,
                            106, 102, 134, 144, 128, 225, 239, 95, 132, 202,
                            154, 213, 118, 19, 63, 183, 108, 215, 134, 118, 115]);
   // get the header (usually from the received request; constructed directly here)
   let hdr = Header::new(Some("dh37fgj492je"),
                         Some(UNIX_EPOCH + Duration::new(1353832234, 0)),
                         Some("j4h3g2"),
                         Some(mac),
                         Some("my-ext-value"),
                         Some(vec![1, 2, 3, 4]),
                         Some("my-app"),
                         Some("my-dlg")).unwrap();

   // build a request object based on what we know
   let hash = vec![1, 2, 3, 4];
   let request = RequestBuilder::new("GET", "localhost", 443, "/resource")
       .hash(&hash[..])
       .request();

   let key = Key::new(vec![99u8; 32], SHA256).unwrap();
   let one_week_in_secs = 7 * 24 * 60 * 60;
   if !request.validate_header(&hdr, &key, Duration::from_secs(5200 * one_week_in_secs)) {
       panic!("header validation failed. Is it 2117 already?");
   }
}

A server which validates bewits looks like this:

use hawk::{RequestBuilder, Credentials, Key, SHA256, Bewit};
use std::time::Duration;
use std::borrow::Cow;

let credentials = Credentials {
    id: "me".to_string(),
    key: Key::new("tok", SHA256).unwrap(),
};

// simulate the client generation of a bewit
let client_req = RequestBuilder::new("GET", "mysite.com", 443, "/resource").request();
let client_bewit = client_req
    .make_bewit_with_ttl(&credentials, Duration::from_secs(10))
    .unwrap();
let request_path = format!("/resource?bewit={}", client_bewit.to_str());

let mut maybe_bewit = None;
let server_req = RequestBuilder::new("GET", "mysite.com", 443, &request_path)
    .extract_bewit(&mut maybe_bewit).unwrap()
    .request();
let bewit = maybe_bewit.unwrap();
assert_eq!(bewit.id(), "me");
assert!(server_req.validate_bewit(&bewit, &credentials.key));

Features

By default, the use_ring feature is enabled, which means that this crate will use ring for all cryptographic operations.

Alternatively, one can configure the crate with the use_openssl feature to use the openssl crate.

If no features are enabled, you must provide a custom implementation of the [hawk::crypto::Cryptographer] trait to the set_cryptographer function, or the cryptographic operations will panic.

Attempting to configure both the use_ring and use_openssl features will result in a build error.

Modules

crypto

hawk must perform certain cryptographic operations in order to function, and applications may need control over which library is used for these.

mac

Structs

Bewit

A Bewit is a piece of data attached to a GET request that functions in place of a Hawk Authentication header. It contains an id, a timestamp, a MAC, and an optional ext value. These are available using accessor functions.

Credentials

Hawk credentials: an ID and a key associated with that ID. The digest algorithm must be agreed between the server and the client, and the length of the key is specific to that algorithm.

Header

Representation of a Hawk Authorization header value (the part following "Hawk ").

Key

Hawk key.

PayloadHasher

A utility for hashing payloads. Feed your entity body to this, then pass the finish result to a request or response.

Request

Request represents a single HTTP request.

RequestBuilder
Response

A Response represents a response from an HTTP server.

ResponseBuilder

Enums

DigestAlgorithm
Error
InvalidBewit

Constants

SHA256
SHA384
SHA512

Type Definitions

Result